package com.chalk.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.chalk.common.util.IdGenerator;
import com.chalk.common.util.Result;
import com.chalk.model.Member;
import com.chalk.model.Ticket;
import com.chalk.model.TicketOrder;
import com.chalk.dao.TicketOrderDao;
import com.chalk.model.TicketOrderItem;
import com.chalk.service.TicketOrderItemService;
import com.chalk.service.TicketOrderService;
import com.chalk.service.TicketService;
import com.chalk.service.WxMiniPayService;
import com.chalk.util.MapUtil;
import com.chalk.util.WxUtil;
import com.chalk.util.wxminipay.WxMiniPayConfig;
import com.chalk.util.wxminipay.WxMiniPayResultSuccess;
import com.chalk.util.wxminipay.WxMiniQueryResult;
import com.chalk.util.wxminipay.WxMiniRequestParam;
import com.chalk.vo.TicketOrderVo;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author glq
 * @since 2020-12-24
 */

@Service
public class TicketOrderServiceImpl extends ServiceImpl<TicketOrderDao, TicketOrder> implements TicketOrderService {
    //localdatetime定义格式
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public int addTicketOrder(TicketOrder entity) {
        return baseMapper.insert(entity);
    }

    @Override
    public int updateTicketOrder(TicketOrder entity) {
        return baseMapper.updateById(entity);
    }


    @Override
    public int deleteTicketOrder(Integer id) {
        return baseMapper.deleteById(id);
    }

    @Autowired
    TicketService ticketService;
    @Autowired
    TicketOrderItemService ticketOrderItemService;

    @Autowired
    WxMiniPayService wxMiniPayService;

    @Override
    public Boolean checkTicketOrderTotal(BigDecimal total, List<TicketOrderItem> ticketOrderItems) {
        BigDecimal totalMoney = new BigDecimal("0");
        for (TicketOrderItem orderItem : ticketOrderItems) {
            BigDecimal t = orderItem.getTicketPrice().multiply(new BigDecimal(orderItem.getTicketNum()));
            totalMoney = totalMoney.add(t);
        }
        if (total.compareTo(totalMoney) == 0) {
            return true;
        }
        return false;
    }

    @Override
    public Boolean checkTicketIsNotExist(List<TicketOrderItem> ticketOrderItems) {
        Boolean f = false;
        for (TicketOrderItem item : ticketOrderItems) {
            Ticket ticket = ticketService.selectOne(new EntityWrapper<Ticket>().eq("is_delete", 0)
                    .eq("ticket_id", item.getTicketId()));
            if (ticket == null) {
                f = true;
            }
        }

        return f;
    }

    @Override
    public Boolean checkTicketStock(List<TicketOrderItem> ticketOrderItems) {
        Boolean f = true;
        for (TicketOrderItem item : ticketOrderItems) {
            Ticket ticket = ticketService.selectOne(new EntityWrapper<Ticket>().eq("is_delete", 0)
                    .eq("ticket_id", item.getTicketId()));
            if (item.getTicketNum().intValue() > ticket.getTicketStock()) {
                f = false;
            }
        }
        return f;

    }

    @Override
    public Boolean updateTicketStock(Integer ticketOrderId) {
        List<TicketOrderItem>ticketOrderItems=ticketOrderItemService.selectList(new EntityWrapper<TicketOrderItem>()
        .eq("is_delete",0).eq("ticket_order_id",ticketOrderId));
        Boolean f = false;
        for (TicketOrderItem item : ticketOrderItems) {
            Ticket ticket = ticketService.selectOne(new EntityWrapper<Ticket>().eq("is_delete", 0)
                    .eq("ticket_id", item.getTicketId()));
            ticket.setTicketStatus(ticket.getTicketStock().intValue() - item.getTicketNum());
            f = ticketService.updateById(ticket);
        }
        return f;
    }

    @Transactional
    @Override
    public Map<String, Object> generateTicketOrder(TicketOrderVo ticketOrderVo, Member member) {
        Map<String, Object> data = new HashMap<>();
        TicketOrder ticketOrder = new TicketOrder();
        ticketOrder.setCreateTime(LocalDateTime.now());
        ticketOrder.setMemberId(member.getMemberId());
        ticketOrder.setTicketOrderNo("TO" + IdGenerator.getIdStr());
        ticketOrder.setTicketOrderTotal(ticketOrderVo.getTicketOrderTotal());
        ticketOrder.setVenueId(ticketOrderVo.getVenueId());
        ticketOrder.setScheduledTime(LocalDateTime.parse(ticketOrderVo.getScheduledTime(), formatter));

        Boolean f = insert(ticketOrder);
        if (f) {
            for (TicketOrderItem i : ticketOrderVo.getTicketOrderItems()) {
                i.setMemberId(member.getMemberId());
                i.setCreateTime(LocalDateTime.now());
                i.setTicketOrderId(ticketOrder.getTicketOrderId());
                ticketOrderItemService.insert(i);
            }
        }
        data.put("ticketOrderId", ticketOrder.getTicketOrderId());
        data.put("ticketOrderNo", ticketOrder.getTicketOrderNo());
        data.put("createTime", ticketOrder.getCreateTime());
        return data;
    }

    @Override
    public String composeTicketName(Integer ticketOrderId) {
        List<TicketOrderItem> orderItems = ticketOrderItemService.selectList(new EntityWrapper<TicketOrderItem>()
                .eq("ticket_order_id", ticketOrderId).eq("is_delete", 0));
        StringBuffer str = new StringBuffer("");

        if (orderItems.size() == 1) {
            return str.append(orderItems.get(0).getTicketName() + "x" + orderItems.get(0).getTicketNum()).toString();
        } else {
            for (TicketOrderItem t : orderItems) {
                str.append(t.getTicketName() + "x" + t.getTicketNum() + ",");
            }
            return str.substring(0, str.length()-1);
        }
    }

    @Override
    public Result generateWxMiniOrder(Integer ticketOrderId,Member member) {
        TicketOrder ticketOrder = selectById(ticketOrderId);
        if (ticketOrder == null) {
            return Result.fail("该订单不存在！");
        }
        if (ticketOrder.getTicketOrderStatus() != 0) {
            return Result.fail("该订单不是未支付状态，无法进行支付");
        }
        ticketOrder.setWxOrderNo("wx"+IdGenerator.getIdStr());
        updateById(ticketOrder);
        Map<String, Object> map = new HashMap<>();

        WxMiniPayResultSuccess resultSuccess = wxMiniPayService.generateWxOrder(composeTicketName(ticketOrderId), ticketOrder.getWxOrderNo(), ticketOrder.getTicketOrderTotal().multiply(new BigDecimal("100")).intValue(),member.getOpenId());
        WxMiniRequestParam wxMiniRequestParam = new WxMiniRequestParam();
        wxMiniRequestParam.setAppid(resultSuccess.appid);
        wxMiniRequestParam.setKey(WxMiniPayConfig.key);
        wxMiniRequestParam.setNonceStr(RandomStringUtils.random(16, true, true));
        wxMiniRequestParam.setPackageQ("prepay_id=" + resultSuccess.prepay_id);
        wxMiniRequestParam.setSignType("MD5");
        wxMiniRequestParam.setTimeStamp(String.valueOf(System.currentTimeMillis() / 1000));
        wxMiniRequestParam.setPaySign(WxUtil.generatorPaySign(wxMiniRequestParam));

        map.put("timeStamp", wxMiniRequestParam.getTimeStamp());
        map.put("nonceStr", wxMiniRequestParam.getNonceStr());
        map.put("package", wxMiniRequestParam.getPackageQ());
        map.put("signType", wxMiniRequestParam.getSignType());
        map.put("paySign", wxMiniRequestParam.getPaySign());

        return Result.success(map);

    }

    @Override
    public Result onlinePaySuccess(Integer ticketOrderId) {
        TicketOrder ticketOrder = selectById(ticketOrderId);
        if (ticketOrder == null) {
            return Result.fail("该订单不存在！");
        }
        if (ticketOrder.getTicketOrderStatus() != 0) {
            return Result.fail("该订单不是未支付状态，无法进行回调");
        }
        WxMiniQueryResult queryResult = wxMiniPayService.queryWxOrder(ticketOrder.getWxOrderNo());
        if(queryResult.trade_state.equals("SUCCESS")){
            //扣库存
            updateTicketStock(ticketOrderId);
            //改状态
            ticketOrder.setTicketOrderStatus(1);
            ticketOrder.setPayTime(LocalDateTime.now());
            updateById(ticketOrder);
            return Result.success("支付成功！");
        }else {
            return Result.fail(queryResult.trade_state_desc);
        }
    }

    @Override
    public Page<TicketOrder> getMyTicketOrdersForPage(Map<String, Object> map) {
        List<String> desc=new ArrayList<>();
        desc.add("tor.create_time");
        Page<TicketOrder>page=new Page<>(MapUtil.getPage(map),MapUtil.getSize(map));
        return page.setRecords(this.baseMapper.getMyTicketOrdersForPage(page,map));
    }
}